
#include "stdafx.h"

#ifdef UNDER_CE

#include <windows.h>
#include <tlhelp32.h>

#include "miscutil.h"
#include "SmpTst.h"
#include "CmdLnPars.h"
#include "RPC.hxx"
#define WINCEMACRO
#include "XAPI.h"



BOOL GetProcInfo(const TCHAR* pszProc, HANDLE* phProc, DWORD* pdwProcId)
{
	BOOL ret=FALSE;

	HANDLE hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0);
	if(INVALID_HANDLE_VALUE == hSnap)
	{
		RETAILMSG(1, (TEXT("CreateToolhelp32Snapshot faild ErrCode:%d\r\n"), GetLastError()));
		return ret;
	}

	PROCESSENTRY32 procEntry;
	procEntry.dwSize=sizeof(procEntry);
	BOOL fRet=Process32First(hSnap, &procEntry);
	while(fRet)
	{
		if(0==_tcsicmp(pszProc, procEntry.szExeFile) )
		{
			RETAILMSG(1, (TEXT("find process %s\r\n"), procEntry.szExeFile));
			*phProc=OpenProcess(0, FALSE, procEntry.th32ProcessID);
			*pdwProcId=procEntry.th32ProcessID;
			ret=TRUE;
			break; 
		}

		fRet=Process32Next(hSnap, &procEntry);
	}

	CloseToolhelp32Snapshot(hSnap);

	return ret;
}

BOOL GetModulBaseAddr(DWORD dwProcId, const TCHAR* pszMod, DWORD* pdwBase)
{
	// find module
	HANDLE hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcId);
	if(INVALID_HANDLE_VALUE==hSnap)
	{
		return FALSE;
	}

	MODULEENTRY32 moduleEntry;
	moduleEntry.dwSize=sizeof(moduleEntry);
	BOOL fRet=Module32First(hSnap, &moduleEntry);
	while(fRet)
	{
		if(0==_tcsicmp(pszMod, moduleEntry.szModule) )
		{
			DEBUGMSG(1, (TEXT("find module %s\r\n"), moduleEntry.szModule));
			break; 
		}

		fRet=Module32Next(hSnap, &moduleEntry);
	}

	CloseToolhelp32Snapshot(hSnap);

	if(!fRet)
	{
		RETAILMSG(1, (TEXT("can't find module:%s\r\n"), pszMod));
		return FALSE;
	}

	*pdwBase=(DWORD)moduleEntry.modBaseAddr;

	return TRUE;
}

_tstring gCF_strProcName;
_tstring gCF_strModuleName;
DWORD gCF_dwFunOff;
DWORD gCF_dwFunAddr;
int gCF_iFunType;
DWORD gCF_dwRet;
DWORD gCF_dwParaNumb;
DWORD gCF_dwPara1;
DWORD gCF_dwPara2;
DWORD gCF_dwPara3;
DWORD gCF_dwPara4;
DWORD gCF_dwPara5;
DWORD gCF_dwPara6;
DWORD gCF_dwPara7;
DWORD gCF_dwPara8;
DWORD gCF_dwPara9;

static ParaInfo v_pi[9]=
{
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
	{PARA_DIR_IN, PARA_TYPE_VAL, 4, 0},
};

static DWORD* v_pdwPara[9]=
{
	&gCF_dwPara1,
	&gCF_dwPara2,
	&gCF_dwPara3,
	&gCF_dwPara4,
	&gCF_dwPara5,
	&gCF_dwPara6,
	&gCF_dwPara7,
	&gCF_dwPara8,
	&gCF_dwPara9,
};


extern "C" void cf_if_xapi_ld(SmpTstFunCntx* pv)
{
	// get process info
	HANDLE hProc;
	DWORD dwProcId;
	if( !GetProcInfo(_T("nk.exe"), &hProc, &dwProcId) )
	{
		SMPTST_RSLT_RETURN(pv, FALSE, (TEXT("can't find nk.exe!")));
	}

	DWORD dwAddr;
	if(!GetModulBaseAddr(dwProcId, _T("xapi.dll"), &dwAddr) )
	{
		SMPTST_RSLT_RETURN(pv, FALSE, (TEXT("can't find module xapi.dll please load it!")));
	}
	
	SMPTST_RSLT_RETURN(pv, TRUE, (TEXT("xapi.dll had loaded!")));
}


extern "C" void cf_call(SmpTstFunCntx* pv)
{
	if(gCF_iFunType>1)
	{
		gCF_iFunType=1;
	}

	// get process info
	HANDLE hProc;
	DWORD dwProcId;
	if( (gCF_strProcName.empty())
		|| !GetProcInfo(gCF_strProcName.c_str(), &hProc, &dwProcId) )
	{
		SMPTST_RSLT_RETURN(pv, FALSE, (TEXT("can't find proc_name:%s specified!"), gCF_strProcName.c_str()));
	}

	DWORD dwAddr;
	if(0==gCF_iFunType)
	{
		if(gCF_strModuleName.empty())
		{
			dwAddr=gCF_dwFunOff;
		}
		else
		{
			if(!GetModulBaseAddr(dwProcId, gCF_strModuleName.c_str(), &dwAddr))
			{
				SMPTST_RSLT_RETURN(pv, FALSE, (TEXT("can't find module_name:%s specified!"), gCF_strModuleName.c_str()));
			}
			dwAddr+=gCF_dwFunOff;
		}
	}
	else
	{
		if(0==gCF_dwFunAddr)
		{
			SMPTST_RSLT_RETURN(pv, FALSE, (TEXT("invalid func_addr:0x%x!"), gCF_dwFunAddr));
		}
		dwAddr=gCF_dwFunAddr;
	}

	for(DWORD i=0; i<9; i++)
	{
		v_pi[i].para=*(v_pdwPara[i]);
	}
	gCF_dwRet=XAPI_DispatchCall(hProc, dwAddr, gCF_dwParaNumb, v_pi);
	for(DWORD i=0; i<9; i++)
	{
		*(v_pdwPara[i])=v_pi[i].para;
	}

	SMPTST_RSLT_RETURN(pv, TRUE, (TEXT("cf_call proc:%s addr:0x%xOk!"), gCF_strProcName.c_str(), dwAddr));
}


SMPTST_GROUP(CALL_FUNCTION, TEXT("CALL FUNCTION"));
	SMPTST_SUB_FUNCTION(cf_if_xapi_ld, TEXT("if_xapi_loaded()"), CALL_FUNCTION);
	SMPTST_SUB_FUNCTION(cf_call, TEXT("cf_ret=call_function(cf_proc, [cf_module], cf_offset|cf_addr, cf_p_numb, [cf_pN...])"), CALL_FUNCTION);


CMDLINE_INIT_NAME_VAL(_T("_cf"), _tstring, gCF_strTstOptions, _T(""), TEXT("USE \"/tst_var:cf_\" TO LIST CALL FUNCTION OPTIONS\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_proc"), _tstring, gCF_strProcName, TEXT("process name\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_module"), _tstring, gCF_strModuleName, TEXT("module name\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_offset"), DWORD, gCF_dwFunOff, TEXT("function offset base on module\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_addr"), DWORD, gCF_dwFunAddr, TEXT("function addr\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_type"), int, gCF_iFunType, TEXT("fun_off:0 fun_addr:1\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_ret"), DWORD, gCF_dwRet, TEXT("function return\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p_numb"), DWORD, gCF_dwParaNumb, TEXT("function para number\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p1"), DWORD, gCF_dwPara1, TEXT("para 1\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p2"), DWORD, gCF_dwPara2, TEXT("para 2\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p3"), DWORD, gCF_dwPara3, TEXT("para 3\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p4"), DWORD, gCF_dwPara4, TEXT("para 4\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p5"), DWORD, gCF_dwPara5, TEXT("para 5\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p6"), DWORD, gCF_dwPara6, TEXT("para 6\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p7"), DWORD, gCF_dwPara7, TEXT("para 7\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p8"), DWORD, gCF_dwPara8, TEXT("para 8\r\n"), FALSE);
CMDLINE_INIT_EXT_NAME_VAL(_T("cf_p9"), DWORD, gCF_dwPara9, TEXT("para 9\r\n"), FALSE);


#endif	//#ifdef UNDER_CE
